JavaServer Pages
1. 개요
1. 개요
자바서버 페이지스(JSP)는 자바를 이용한 서버 사이드 스크립트 언어이다. 썬 마이크로시스템즈에 의해 개발되어 1999년에 최초로 등장했다. 주된 용도는 동적 웹 페이지를 생성하고 웹 애플리케이션을 개발하는 것이다.
JSP는 HTML 문서 안에 자바 코드를 삽입하여 동적인 콘텐츠를 생성하는 방식을 사용한다. 이 기술은 자바 서블릿 기술을 확장한 것으로, 서블릿을 작성하는 것보다 더 쉽게 웹 페이지를 만들 수 있도록 설계되었다. JSP 파일은 최종적으로 웹 서버 내의 JSP 컨테이너에 의해 서블릿으로 변환되고 실행된다.
웹 개발 분야에서 JSP는 전통적인 서버 사이드 렌더링 방식의 웹 애플리케이션 구축에 널리 사용되어 왔다. 이 기술은 관련 분야인 자바 EE 플랫폼의 핵심 구성 요소 중 하나로 자리 잡았다.
2. 역사
2. 역사
자바서버 페이지스는 1999년 썬 마이크로시스템즈에 의해 처음 소개되었다. 이 기술은 자바 기반의 서블릿 기술을 보완하고 확장하기 위해 개발되었으며, HTML 문서 내에 자바 코드를 직접 삽입하여 동적 웹 페이지를 보다 쉽게 생성할 수 있도록 설계되었다. 초기에는 서버 사이드 스크립트 언어로서 ASP나 PHP와 유사한 접근 방식을 취했지만, 자바 플랫폼의 강력한 기능과 이식성을 그 기반으로 삼았다.
이 기술의 등장은 당시 웹 개발 환경에서 정적 콘텐츠에서 벗어나 복잡한 비즈니스 로직을 처리하는 애플리케이션을 구축하려는 수요에 부응한 것이었다. 서블릿만으로는 프레젠테이션 계층을 구성하는 데 다소 번거로움이 있었는데, 자바서버 페이지스는 뷰를 담당하는 부분의 개발 생산성을 크게 향상시켰다. 이를 통해 개발자들은 비즈니스 로직과 사용자 인터페이스를 보다 명확하게 분리할 수 있는 기반을 마련하게 되었다.
자바서버 페이지스는 이후 자바 커뮤니티 프로세스를 통해 표준화가 진행되었고, 다양한 애플리케이션 서버와 웹 컨테이너에서 지원되는 핵심 웹 기술로 자리 잡았다. 시간이 지나면서 복잡한 자바 코드를 JSP 페이지 내에서 최소화하고, JSTL과 EL 같은 표현 언어를 도입하는 등 발전을 거듭하여 현대적인 MVC 패턴 기반 웹 애플리케이션 개발의 중요한 구성 요소가 되었다.
3. 기본 문법과 구조
3. 기본 문법과 구조
3.1. 지시자(Directive)
3.1. 지시자(Directive)
지시자는 JSP 페이지가 서블릿으로 변환될 때 웹 애플리케이션 서버에 전달하는 메시지이다. 페이지의 전반적인 설정 정보를 지정하는 데 사용되며, 주로 페이지의 속성, 포함할 외부 파일, 사용할 태그 라이브러리를 선언한다. 지시자는 <%@로 시작하여 %>로 끝나는 구문으로 작성되며, 페이지의 어느 위치에든 선언할 수 있으나 일반적으로 문서 상단에 위치시킨다.
주요 지시자로는 page, include, taglib가 있다. page 지시자는 해당 JSP 페이지의 속성을 정의하며, 콘텐츠 타입, 인코딩, 사용할 자바 클래스의 임포트, 세션 사용 여부 등을 설정한다. include 지시자는 번역 시간에 다른 파일의 내용을 현재 JSP 페이지에 삽입할 때 사용하며, 주로 공통으로 사용되는 헤더나 푸터, 네비게이션 메뉴 파일을 포함시키는 데 유용하다. taglib 지시자는 JSTL과 같은 사용자 정의 태그 라이브러리를 사용하겠다고 선언할 때 필요하다.
이러한 지시자는 JSP 페이지가 서블릿 소스 코드로 변환되는 과정에서 처리되며, 최종 생성되는 HTML 문서에는 직접적으로 나타나지 않는다. 지시자를 통해 페이지의 동작 방식을 제어함으로써, 개발자는 보다 구조적이고 유지보수가 쉬운 웹 애플리케이션을 구성할 수 있다.
3.2. 선언(Declaration)
3.2. 선언(Declaration)
JSP 선언(Declaration)은 자바 프로그래밍 언어의 메서드나 변수를 JSP 페이지 내에 정의하기 위해 사용하는 요소이다. 이는 JSP 페이지가 서블릿으로 변환될 때, 생성되는 서블릿 클래스의 멤버(인스턴스 변수나 메서드)를 선언하는 데 쓰인다. 선언은 <%!로 시작하여 %>로 끝나는 태그 안에 자바 코드를 작성하는 방식으로 이루어진다.
선언부에 정의된 변수는 해당 JSP 페이지에서 생성되는 서블릿의 인스턴스 변수가 되며, 이는 페이지의 모든 요청에 걸쳐 공유되는 전역 변수의 성격을 가진다. 마찬가지로 선언부에 정의된 메서드는 서블릿 클래스의 멤버 메서드가 되어, JSP 페이지 내의 다른 스크립팅 요소나 표현식에서 호출하여 사용할 수 있다. 이는 스크립틀릿 내에 작성된 지역 변수나 코드와는 구분되는 중요한 특징이다.
선언의 사용은 주로 JSP 페이지 전반에서 재사용되는 유틸리티 메서드를 정의하거나, 페이지의 상태를 유지해야 하는 인스턴스 변수를 설정할 때 유용하다. 그러나 지나치게 많은 비즈니스 로직을 선언부에 포함시키는 것은 MVC 패턴의 관점에서 권장되지 않으며, 자바빈즈나 별도의 자바 클래스를 활용하는 것이 일반적이다.
3.3. 스크립틀릿(Scriptlet)
3.3. 스크립틀릿(Scriptlet)
스크립틀릿은 자바 코드를 JSP 페이지 내에 직접 삽입하여 실행할 수 있게 하는 가장 기본적인 요소이다. 스크립틀릿은 <%와 %> 태그로 둘러싸여 있으며, 이 태그 안에 작성된 모든 자바 코드는 서블릿으로 변환될 때 _jspService 메서드 내부에 그대로 삽입되어 실행된다. 이는 HTML이나 다른 정적 마크업과 동적으로 생성될 콘텐츠를 혼합하여 작성할 수 있게 해주며, JSP가 동적 웹 페이지를 생성하는 핵심 메커니즘을 제공한다.
주로 변수 선언, 제어문(if, for, while 등), 메서드 호출과 같은 로직을 구현하는 데 사용된다. 예를 들어, 데이터베이스에서 조회한 결과를 반복문을 통해 HTML 테이블로 출력하거나, 사용자 요청에 따른 조건부 화면 표시 등을 처리할 수 있다. 스크립틀릿 내에서는 JSP가 제공하는 내장 객체(예: request, response, out)를 별도의 선언 없이 바로 사용할 수 있어 편리하다.
그러나 스크립틀릿의 과도한 사용은 JSP 페이지에 비즈니스 로직과 표현 로직이 뒤섞이는 문제를 초래하여 코드의 가독성과 유지보수성을 현저히 떨어뜨린다. 이는 MVC 패턴의 원칙에 위배되며, 이러한 단점을 보완하기 위해 후속 기술인 JSTL과 EL이 등장하게 된 주요 동기가 되었다. 현대적인 자바 웹 애플리케이션 개발에서는 스크립틀릿보다는 이러한 태그 라이브러리와 표현 언어를 사용하는 것을 권장한다.
3.4. 표현식(Expression)
3.4. 표현식(Expression)
표현식은 자바 코드의 결과를 웹 페이지에 간단히 출력하기 위해 사용되는 JSP 구성 요소이다. 표현식은 <%=와 %> 태그로 둘러싸여 있으며, 이 태그 사이에 위치한 자바 표현식의 평가 결과가 문자열로 변환되어 클라이언트의 응답에 직접 삽입된다. 이는 스크립틀릿 내에서 out.print() 메서드를 사용하는 것보다 훨씬 간결한 문법을 제공한다.
표현식은 주로 변수의 값, 객체의 프로퍼티, 메서드 호출의 반환값 등을 HTML 코드 내에 동적으로 삽입할 때 활용된다. 예를 들어, 현재 시간을 표시하거나 데이터베이스 조회 결과를 테이블 형태로 나열하는 등의 작업에 적합하다. 표현식 내부의 코드는 서버에서 실행되며, 그 결과만이 사용자의 웹 브라우저로 전송된다.
표현식 태그는 JSP 엔진에 의해 서블릿 소스 코드로 변환될 때 out.print() 문으로 변경된다는 점이 특징이다. 따라서 표현식은 문장의 끝을 의미하는 세미콜론(;)을 포함해서는 안 된다. 이는 JSP의 기본 문법 중 하나로, 초보자가 자주 범하는 오류 중 하나이기도 하다.
이러한 표현식의 사용은 JSP 초기 버전에서 동적 콘텐츠를 생성하는 핵심 방법이었으나, 이후 등장한 JSTL과 EL은 표현식의 역할을 대체하고 보완하여 더 깔끔하고 유지보수하기 쉬운 코드 작성을 가능하게 했다.
3.5. 액션 태그(Action Tag)
3.5. 액션 태그(Action Tag)
액션 태그는 JSP 페이지 내에서 특정 동작을 수행하기 위해 사용되는 XML 기반의 태그이다. 이 태그들은 페이지의 실행 흐름을 제어하거나, 다른 자원을 포함시키거나, 자바빈즈 컴포넌트를 조작하는 등의 기능을 제공한다. 서블릿 코드로 변환될 때는 해당 기능을 수행하는 자바 코드로 대체된다.
액션 태그는 크게 표준 액션 태그와 사용자 정의 태그로 나눌 수 있다. 표준 액션 태그는 JSP 명세에 정의되어 있어 별도의 라이브러리 없이 사용할 수 있다. 대표적인 예로는 다른 페이지로의 포워딩을 위한 jsp:forward, 다른 JSP나 HTML 파일을 현재 페이지에 포함시키는 jsp:include, 그리고 자바빈즈 객체를 생성하고 속성을 설정하는 jsp:useBean, jsp:setProperty, jsp:getProperty 태그 등이 있다.
사용자 정의 태그는 개발자가 직접 태그 라이브러리를 만들어 기능을 확장할 수 있는 방법이다. 이는 복잡한 로직을 태그 형태로 캡슐화하여 JSP 페이지에서 HTML처럼 간결하게 사용할 수 있게 해준다. 사용자 정의 태그의 발전된 형태가 바로 JSTL이다.
액션 태그의 사용은 JSP 페이지 내에 자바 코드를 직접 작성하는 스크립틀릿의 사용을 줄이고, 보다 깔끔하고 유지보수하기 쉬운 뷰 레이어를 구성하는 데 기여한다. 이는 MVC 패턴에서 JSP가 뷰 역할을 수행하도록 하는 데 중요한 요소가 된다.
4. 내장 객체
4. 내장 객체
JSP는 서블릿 컨테이너가 JSP 페이지를 서블릿으로 변환하고 실행할 때, 개발자가 별도의 선언 없이도 사용할 수 있는 여러 객체를 자동으로 생성하여 제공한다. 이러한 객체들을 내장 객체라고 하며, 이들은 서블릿 API의 특정 클래스들로 미리 구현되어 있어 스크립틀릿이나 표현식 내에서 즉시 참조할 수 있다.
주요 내장 객체로는 요청 정보를 담는 request(HttpServletRequest), 응답 정보를 조작하는 response(HttpServletResponse), 페이지 실행 컨텍스트를 제공하는 pageContext, 사용자 세션을 관리하는 session(HttpSession), 웹 애플리케이션 전체의 정보를 저장하는 application(ServletContext), 출력 스트림을 제공하는 out(JspWriter), 서블릿 자신을 가리키는 page, 그리고 예외 정보를 처리하는 exception 객체 등이 있다. 이 객체들을 통해 개발자는 HTTP 요청 파라미터 접근, 세션 관리, 애플리케이션 범위의 속성 설정 등 웹 개발의 핵심 기능을 쉽게 구현할 수 있다.
내장 객체의 사용은 JSP 프로그래밍을 단순화시키는 핵심 요소이다. 예를 들어, request.getParameter("name")과 같은 코드로 클라이언트의 폼 데이터를 받아올 수 있으며, session.setAttribute("user", userObj)로 로그인한 사용자 정보를 서버에 유지할 수 있다. 또한 application 객체를 통해 데이터베이스 연결 풀과 같은 애플리케이션 자원을 모든 사용자가 공유하도록 관리할 수 있다.
이러한 내장 객체들은 JSP 페이지의 라이프사이클 동안 특정 시점에 생성되고, 각각의 유효 범위(스코프)를 가진다. request 객체는 하나의 요청이 처리되는 동안, session 객체는 사용자의 브라우저 세션이 유지되는 동안, application 객체는 웹 애플리케이션이 서버에 배포되어 있는 동안 존재한다. 이 범위 개념은 자바 빈즈나 MVC 패턴에서 데이터를 전달하고 공유하는 데 중요한 기초가 된다.
5. 라이프사이클
5. 라이프사이클
JavaServer Pages의 라이프사이클은 서블릿의 라이프사이클과 밀접하게 연관되어 있다. JSP 페이지는 최초 요청이 발생하면 웹 애플리케이션 서버에 의해 자바 서블릿 소스 코드로 변환(번역)되고, 이후 자바 컴파일러에 의해 서블릿 클래스 파일로 컴파일된다. 이렇게 생성된 서블릿은 메모리에 로드되어 초기화된 후 요청을 처리하게 된다. 이 과정은 일반적으로 최초 요청 시 한 번만 수행되며, 이후 요청은 이미 생성된 서블릿 인스턴스를 재사용하여 효율적으로 처리한다.
라이프사이클의 주요 단계는 번역, 컴파일, 로딩 및 초기화, 요청 처리, 소멸으로 구분할 수 있다. 번역 단계에서는 JSP 페이지의 지시자, 스크립틀릿, 표현식 등의 요소가 서블릿 소스 코드로 변환된다. 컴파일 단계에서는 이 소스 코드가 실행 가능한 바이트코드로 컴파일된다. 이후 서블릿 컨테이너는 jspInit() 메서드를 호출하여 서블릿을 초기화하고, 요청이 들어올 때마다 _jspService() 메서드를 호출하여 동적 콘텐츠를 생성하여 응답한다.
JSP 페이지가 수정되거나 웹 애플리케이션이 재배포되는 등의 변경 사항이 발생하면, 컨테이너는 기존에 컴파일된 클래스를 폐기하고 새로운 라이프사이클을 다시 시작한다. 이는 개발 중 수정 사항을 즉시 반영할 수 있게 해준다. 라이프사이클의 마지막 단계에서는 서블릿 컨테이너가 jspDestroy() 메서드를 호출하여 자원을 해제하고 서블릿 인스턴스를 소멸시킨다.
이러한 라이프사이클을 통해 JSP는 정적 웹 페이지와 달리 매 요청 시점에 데이터를 처리하고 HTML을 동적으로 생성할 수 있다. 이 과정은 서블릿 기술을 기반으로 하므로, JSP 개발자는 서블릿의 동작 원리를 이해하는 것이 성능 최적화와 문제 해결에 도움이 된다.
6. MVC 패턴과의 연관
6. MVC 패턴과의 연관
JSP는 초기에는 비즈니스 로직과 프레젠테이션 로직이 한 페이지에 혼재하는 방식으로 사용되곤 했다. 이는 스파게티 코드를 유발하고 유지보수를 어렵게 만드는 단점이 있었다. 이러한 문제를 해결하기 위해 MVC 패턴이 JSP 기반 웹 애플리케이션 설계에 널리 적용되었다. MVC 패턴은 애플리케이션을 모델, 뷰, 컨트롤러라는 세 가지 역할로 분리하여 개발하는 소프트웨어 디자인 패턴이다.
JSP는 주로 MVC 패턴에서 뷰의 역할을 담당한다. 즉, 서블릿이나 다른 컨트롤러 컴포넌트가 처리한 비즈니스 로직의 결과 데이터(모델)를 전달받아, 이를 HTML 형태로 사용자에게 보여주는 프레젠테이션 계층으로 사용된다. 이때 JSP 페이지 내에서는 가능한 한 자바 코드를 최소화하고, JSTL과 EL을 활용하여 모델 데이터를 표시하는 데 집중하는 것이 권장된다.
컨트롤러의 역할은 일반적으로 서블릿이 담당한다. 서블릿은 클라이언트의 요청을 받아, 필요한 비즈니스 로직을 처리하거나 모델 객체를 생성 및 조작한 후, 그 결과를 적절한 JSP 뷰 페이지로 포워딩한다. 이렇게 역할을 분리함으로써, 웹 디자이너는 화면 디자인에, 개발자는 로직 구현에 각각 집중할 수 있으며, 애플리케이션의 확장성과 유지보수성이 크게 향상된다. 이러한 MVC 구조는 스프링 MVC와 같은 많은 자바 웹 프레임워크의 기반이 되었다.
7. JSTL과 EL
7. JSTL과 EL
JSTL은 JSP 표준 태그 라이브러리이다. 이는 JSP 페이지 내에서 자바 코드를 직접 작성하는 스크립틀릿의 사용을 줄이고, 반복, 조건문, 데이터베이스 쿼리, 국제화와 같은 일반적인 기능을 태그 형태로 제공하기 위해 도입되었다. JSTL은 코어 태그, 포맷팅 태그, SQL 태그, XML 태그, 함수 태그 등 여러 카테고리로 나뉘며, 특히 <c:forEach>나 <c:if>와 같은 코어 태그는 MVC 패턴에서 뷰 레이어의 로직을 깔끔하게 표현하는 데 필수적이다. JSTL의 사용은 JSP 페이지의 가독성과 유지보수성을 크게 향상시켰다.
EL은 표현 언어로, JSP 2.0 버전부터 표준으로 채택되었다. EL의 주요 목적은 JSP 페이지에서 자바빈즈의 프로퍼티나 컬렉션, 내장 객체에 저장된 데이터에 쉽게 접근할 수 있도록 하는 것이다. ${user.name}과 같은 간결한 구문을 사용하여, 기존의 <%= %> 표현식이나 복잡한 스크립틀릿 코드 없이도 값을 출력할 수 있다. EL은 또한 산술 연산, 논리 연산, 관계 연산 및 널 체크를 지원하여 뷰 단에서의 간단한 연산 처리도 가능하게 한다.
JSTL과 EL은 상호 보완적으로 사용된다. JSTL 태그의 속성 값으로 EL 표현식을 사용하는 것이 일반적이며, 이를 통해 동적인 값을 태그에 전달할 수 있다. 예를 들어, <c:if test="${user.age >= 20}">와 같이 조건을 평가할 수 있다. 이 조합은 JSP 페이지에서 스크립틀릿의 의존도를 극도로 낮추고, 태그 기반의 선언적 프로그래밍 방식을 가능하게 하여, 웹 애플리케이션의 프레젠테이션 계층을 더욱 깔끔하고 효율적으로 만든다.
8. 장단점
8. 장단점
JSP는 자바 기반의 서버 사이드 기술로서, 웹 개발에서 널리 사용되면서 명확한 장점과 단점을 가지고 있다.
주요 장점으로는 우선 자바 언어의 강력한 생태계를 그대로 활용할 수 있다는 점이다. 자바의 풍부한 API와 오픈 소스 라이브러리, 그리고 플랫폼 독립성이라는 특징을 서블릿과 함께 공유한다. 또한, HTML 코드 내에 자바 코드를 직접 삽입하는 방식은 초보자에게 비교적 쉽게 접근할 수 있는 환경을 제공하며, 동적 웹 페이지를 빠르게 프로토타이핑하는 데 유리하다. JSP는 또한 서블릿으로 변환되어 실행되므로, 서블릿이 제공하는 강력한 서버 측 기능과 보안성을 그대로 누릴 수 있다.
반면, 단점도 존재한다. 가장 큰 문제는 비즈니스 로직과 프레젠테이션 로직이 한 페이지에 혼재될 수 있다는 점이다. 이는 스파게티 코드를 유발하여 애플리케이션의 유지보수성을 크게 떨어뜨린다. 또한, 페이지 내에 과도한 자바 코드가 포함되면 프론트엔드 개발자와의 협업이 어려워질 수 있다. 이러한 구조적 문제를 해결하기 위해 등장한 패러다임이 MVC 패턴이며, JSP는 주로 뷰(View) 계층의 기술로 진화하게 된다.
성능 측면에서는 최초 요청 시 JSP 파일이 서블릿 소스 코드로 변환되고 컴파일되는 과정을 거치므로, 약간의 초기 지연 시간이 발생할 수 있다. 그러나 한 번 컴파일된 후에는 실행 속도가 빠르다. 현대적인 웹 애플리케이션 개발에서는 순수 JSP만을 사용하기보다는 Spring MVC 같은 프레임워크의 뷰 기술로, 또는 JSTL과 EL을 적극 활용하여 단점을 보완하는 방식이 일반적이다.
9. 관련 기술 및 프레임워크
9. 관련 기술 및 프레임워크
JSP는 자바 기반의 웹 기술 생태계 내에서 여러 관련 기술 및 프레임워크와 밀접하게 연동되어 사용된다. 가장 근본적으로 JSP는 서블릿 기술의 확장으로, 실행 시 서블릿 소스 코드로 변환된 후 컴파일되어 동작한다. 이는 JSP가 서블릿의 편리한 뷰 템플릿 역할을 수행함을 의미한다. 또한, 자바빈즈와 결합하여 비즈니스 로직 컴포넌트를 쉽게 활용할 수 있는 구조를 제공한다.
JSP의 한계를 보완하고 개발 효율성을 높이기 위해 JSTL과 EL이 도입되었다. JSTL은 반복문이나 조건문 같은 제어 로직을 태그 라이브러리 형태로 표준화하여 제공하며, EL은 스크립트 요소 없이 객체의 속성에 쉽게 접근할 수 있는 표현 언어이다. 이 두 기술은 JSP 페이지 내에서 자바 코드의 사용을 최소화하고 깔끔한 뷰 관리를 가능하게 한다.
MVC 패턴의 정착과 함께, JSP는 주로 뷰 계층을 담당하는 기술로 자리 잡았다. 이를 뒷받침하는 다양한 자바 EE 기반의 웹 애플리케이션 프레임워크들이 JSP를 주요 뷰 기술로 채택했다. 대표적으로 스트러츠, 스프링 MVC, 자바서버 페이스즈 등이 있으며, 이러한 프레임워크들은 컨트롤러와 모델 처리 로직을 표준화하고 JSP를 효율적으로 통합하는 구조를 제공한다.
10. 여담
10. 여담
JSP는 초기 자바 기반 웹 개발의 핵심 기술로 자리 잡았으며, 특히 서블릿과의 밀접한 관계가 특징이다. JSP 페이지는 실제로 서블릿 컨테이너에 의해 서블릿 클래스로 변환되어 실행되는데, 이는 개발자가 HTML과 유사한 형태로 코드를 작성하더라도 결국 자바 코드로 번역되어 동작한다는 의미이다. 이러한 변환 과정 덕분에 서블릿의 강력한 기능을 활용하면서도 비교적 쉽게 웹 페이지를 작성할 수 있었다.
JSP의 등장은 ASP나 PHP와 같은 당시 경쟁 기술에 대응하기 위한 썬 마이크로시스템즈의 전략이었다. 자바 생태계의 일원으로서, JSP는 자바 EE 플랫폼의 중요한 구성 요소가 되었고, 대규모 기업용 소프트웨어 개발에 널리 채택되었다. 시간이 지나면서 순수 JSP로 모든 로직을 처리하는 방식은 유지보수의 어려움을 초래했고, 이는 MVC 패턴의 도입과 JSTL, EL 같은 보조 기술의 발전을 촉진하는 계기가 되었다.
오늘날에는 스프링 부트를 비롯한 현대적인 자바 웹 프레임워크들이 더 선호되지만, JSP는 여전히 레거시 시스템에서 많이 발견된다. 또한 JSP의 기본 개념과 라이프사이클에 대한 이해는 자바 백엔드 개발의 기초를 형성하며, 서버 측에서 HTML이 동적으로 생성되는 원리를 배우는 데 유용한 교재 역할을 하고 있다.
